package logger

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
	"strings"
)

var (
	infoLogger  *zap.Logger
	errorLogger *zap.Logger
	Level       uint8
)

type LogConfig struct {
	InfoFilePath  string // info日志路径
	ErrorFilePath string // error日志路径
	MaxSizeMB     int    // 单文件最大MB
	MaxBackupDays int    // 保留天数
	EnableConsole bool   // 是否输出控制台
}

func customColorLevelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
	switch level {
	case zapcore.InfoLevel:
		enc.AppendString("\x1b[32mINFO\x1b[0m") // 32 为绿色代码
	default:
		// 其他级别保持默认颜色
		zapcore.CapitalColorLevelEncoder(level, enc)
	}
}

func InitLogger(cfg LogConfig) {
	// 公共编码器配置
	encoderConfig := zapcore.EncoderConfig{
		TimeKey: "ts",
		//LevelKey:   "level",
		MessageKey:    "msg",
		CallerKey:     "caller", //打印代码行数
		StacktraceKey: "stacktrace",
		EncodeTime:    zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
		EncodeLevel:   customColorLevelEncoder,
		EncodeCaller:  zapcore.ShortCallerEncoder,
	}
	// 创建分级写入器
	infoWriter := getLumberjackWriter(cfg.InfoFilePath, cfg)
	errorWriter := getLumberjackWriter(cfg.ErrorFilePath, cfg)

	// 构建分级核心
	infoCore := newCore(zapcore.NewJSONEncoder(encoderConfig), infoWriter,
		zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
			return lvl == zapcore.Level(Level)
		}))

	errorCore := newCore(zapcore.NewJSONEncoder(encoderConfig), errorWriter,
		zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
			return lvl >= zapcore.ErrorLevel
		}))

	// 合并核心到Logger
	infoLogger = zap.New(infoCore, zap.AddCaller(), zap.AddCallerSkip(1))
	errorLogger = zap.New(errorCore, zap.AddCaller(), zap.AddCallerSkip(1))

	// 控制台输出（可选）
	if cfg.EnableConsole {
		consoleCore := zapcore.NewCore(
			zapcore.NewConsoleEncoder(encoderConfig),
			zapcore.Lock(os.Stdout),
			zap.ErrorLevel,
		)
		infoLogger = infoLogger.WithOptions(zap.WrapCore(func(c zapcore.Core) zapcore.Core {
			return zapcore.NewTee(c, consoleCore)
		}))
	}
}

func getLumberjackWriter(path string, cfg LogConfig) zapcore.WriteSyncer {
	return zapcore.AddSync(&lumberjack.Logger{
		Filename:   path,
		MaxSize:    cfg.MaxSizeMB,
		MaxAge:     cfg.MaxBackupDays,
		MaxBackups: 30,
		Compress:   true,
		LocalTime:  true,
	})
}

func newCore(encoder zapcore.Encoder, ws zapcore.WriteSyncer, enab zapcore.LevelEnabler) zapcore.Core {
	return zapcore.NewCore(
		encoder,
		zapcore.NewMultiWriteSyncer(ws),
		enab,
	)
}

// 分级日志方法
func Info(msg string, fields ...zap.Field) {
	infoLogger.Info(msg, fields...)
}

func Error(msg string, fields ...zap.Field) {
	if !strings.Contains(msg, "no such file or directory") {
		errorLogger.Error(msg, fields...)
	}
}
